package com.platform.file.controller;

import com.platform.common.core.exception.ServiceException;
import com.platform.common.core.utils.StringUtils;
import com.platform.common.security.annotation.RepeatSubmit;
import com.platform.common.security.utils.AESUtil_SC;
import com.platform.file.constant.SysFileConstants;
import com.platform.file.domain.DicFileLog;
import com.platform.file.service.IDicFileLogService;
import com.platform.file.service.ISysFileService;
import com.platform.file.utils.FileUploadUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Objects;

/**
 * @Description: 共享文件接口
 * @Author: wcs
 * @Date: 2024-03-22 14:20
 **/
@Slf4j
@RestController
@RequestMapping("/share")
public class ShareFileController {

    @Resource
    private IDicFileLogService dicFileLogService;
    @Resource
    private ISysFileService sysFileService;

    @GetMapping("/download/{fileKey}")
    @RepeatSubmit(message = "下载过于频繁,请稍后再试")
    public void download(@PathVariable("fileKey") String fileKey, HttpServletResponse response) {
        if (StringUtils.isBlank(fileKey)) {
            throw new ServiceException("文件唯一值不存在");
        }
        // 查询文件
        DicFileLog dicFileLog = dicFileLogService.selectDicFileLogByFileKey(fileKey);
        if (Objects.isNull(dicFileLog)) {
            throw new ServiceException("文件不存在");
        }
        String fileUrl;
        String bucketName;
        if (StringUtils.isNotBlank(dicFileLog.getFileUrl())) {
            fileUrl = dicFileLog.getFileUrl();
            bucketName = dicFileLog.getBucketName();
        } else if (StringUtils.isNotBlank(dicFileLog.getFileUrlSecret())) {
            try {
                fileUrl = AESUtil_SC.decryptNoBase64(dicFileLog.getFileUrlSecret(), SysFileConstants.FILESECRET);
                bucketName = FileUploadUtils.getBucketName(fileUrl);
            } catch (Exception e) {
                log.error("文件下载异常,fileKey:{}", fileKey);
                throw new ServiceException("文件路径密钥解析异常");
            }
        } else {
            log.error("文件下载异常,fileKey:{}", fileKey);
            throw new ServiceException("文件存储异常,无法获取文件路径");
        }
        try (
                InputStream in = sysFileService.downLoadFileNew(bucketName, fileUrl.replaceFirst(bucketName + "/", ""));
                ServletOutputStream responseOutputStream = response.getOutputStream()
        ) {
            if (Objects.isNull(in)) {
                log.error("文件下载异常,fileKey:{}", fileKey);
                throw new ServiceException("文件下载异常");
            }
            String filename = dicFileLog.getFileName();
            String headerValue = "attachment; filename=\"" + URLEncoder.encode(filename, "UTF-8") + "\"";
            response.setHeader("Content-Disposition", headerValue);
            int len;
            byte[] bytes = new byte[1024];
            while ((len = in.read(bytes)) != -1) {
                responseOutputStream.write(bytes, 0, len);
            }
            responseOutputStream.flush();
        } catch (Exception e) {
            log.error("文件下载异常,fileKey:{}", fileKey, e);
            throw new ServiceException("文件下载异常");
        }
    }

    @GetMapping("/preview/{fileKey}")
    @RepeatSubmit(message = "预览过于频繁,请稍后再试")
    public void preview(@PathVariable("fileKey") String fileKey, HttpServletResponse response) {
        if (StringUtils.isBlank(fileKey)) {
            throw new ServiceException("文件唯一值不存在");
        }

        // 查询文件信息
        DicFileLog dicFileLog = dicFileLogService.selectDicFileLogByFileKey(fileKey);
        if (Objects.isNull(dicFileLog)) {
            throw new ServiceException("文件不存在");
        }

        String fileUrl;
        String bucketName;
        // 解析文件路径（逻辑与原下载一致）
        if (StringUtils.isNotBlank(dicFileLog.getFileUrl())) {
            fileUrl = dicFileLog.getFileUrl();
            bucketName = dicFileLog.getBucketName();
        } else if (StringUtils.isNotBlank(dicFileLog.getFileUrlSecret())) {
            try {
                fileUrl = AESUtil_SC.decryptNoBase64(dicFileLog.getFileUrlSecret(), SysFileConstants.FILESECRET);
                bucketName = FileUploadUtils.getBucketName(fileUrl);
            } catch (Exception e) {
                log.error("文件预览异常,fileKey:{}", fileKey);
                throw new ServiceException("文件路径密钥解析异常");
            }
        } else {
            log.error("文件预览异常,fileKey:{}", fileKey);
            throw new ServiceException("文件存储异常,无法获取文件路径");
        }

        try (
                InputStream in = sysFileService.downLoadFileNew(bucketName, fileUrl.replaceFirst(bucketName + "/", ""));
                ServletOutputStream responseOutputStream = response.getOutputStream()
        ) {
            if (Objects.isNull(in)) {
                log.error("文件预览异常,fileKey:{}", fileKey);
                throw new ServiceException("文件预览异常");
            }

            // 1. 获取文件名和后缀，用于设置Content-Type
            String filename = dicFileLog.getFileName();
            String fileSuffix = FileUploadUtils.getSuffixNameName(filename); // 假设该工具类可获取文件后缀（如.jpg、.pdf）

            // 2. 设置响应头：告诉浏览器在线预览（而非下载）
            // Content-Disposition: inline 表示在线预览
            String encodedFilename = URLEncoder.encode(filename, "UTF-8");
            response.setHeader("Content-Disposition", "inline; filename=\"" + encodedFilename + "\"");

            // 3. 设置正确的Content-Type（关键：浏览器根据该类型决定如何预览）
            String contentType = getContentTypeBySuffix(fileSuffix);
            response.setContentType(contentType);

            // 4. 写入文件流到响应
            int len;
            byte[] bytes = new byte[1024];
            while ((len = in.read(bytes)) != -1) {
                responseOutputStream.write(bytes, 0, len);
            }
            responseOutputStream.flush();

        } catch (Exception e) {
            log.error("文件预览异常,fileKey:{}", fileKey, e);
            throw new ServiceException("文件预览异常");
        }
    }

    /**
     * 根据文件后缀获取对应的Content-Type
     */
    private String getContentTypeBySuffix(String fileSuffix) {
        if (StringUtils.isBlank(fileSuffix)) {
            return "application/octet-stream"; // 默认二进制流（可能触发下载）
        }
        // 常见可预览文件类型映射（根据业务需求扩展）
        switch (fileSuffix.toLowerCase()) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            case "pdf":
                return "application/pdf";
            case "txt":
                return "text/plain; charset=UTF-8";
            case "html":
                return "text/html; charset=UTF-8";
            case "doc":
                return "application/msword";
            case "docx":
                return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
            case "xls":
                return "application/vnd.ms-excel";
            case "xlsx":
                return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            default:
                // 其他类型可能无法预览，返回默认类型（浏览器可能提示下载）
                return "application/octet-stream";
        }
    }

}
